package mspbots.data.tl.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.*;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * com.mspbots.sync.config.RabbitConfigurer
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/7/29
 */
@Configuration
@RequiredArgsConstructor
public class RabbitConfiguration {

    private final AmqpAdmin amqpAdmin;

    @Bean
    public void syncDatasetScriptExchange() {
        Exchange exchange = ExchangeBuilder.directExchange("msp.dataset").build();
        this.amqpAdmin.declareExchange(exchange);
        Queue queue = QueueBuilder.durable("dataset.refresh.script").build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("dataset.refresh").noargs());
    }

    @PostConstruct
    public void declareAutotaskExchange() {
        Exchange exchange = ExchangeBuilder.directExchange("data.auto-task.sync").build();
        this.amqpAdmin.declareExchange(exchange);

        Map<String, Object> args = new HashMap<>(2);
        args.put("x-dead-letter-exchange", "data.auto-task.sync");
        args.put("x-dead-letter-routing-key", "auto-task-bad-message-key");
        //ticket
        Queue queue = QueueBuilder.durable("auto-task.tickets.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-tickets-sync-key").noargs());
        //users
        queue = QueueBuilder.durable("auto-task.users.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-user-sync-key").noargs());

        //companies
        queue = QueueBuilder.durable("auto-task.companies.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-companies-sync-key").noargs());

        //contact
        queue = QueueBuilder.durable("auto-task.contacts.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-contacts-sync-key").noargs());


        //projects
        queue = QueueBuilder.durable("auto-task.projects.tl").build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-projects-sync-key").noargs());

        //tasks
        queue = QueueBuilder.durable("auto-task.tasks.tl").build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-tasks-sync-key").noargs());


        //departments
        queue = QueueBuilder.durable("auto-task.departments.tl").build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-departments-sync-key").noargs());

        //contracts
        queue = QueueBuilder.durable("auto-task.contracts.tl").build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-contracts-sync-key").noargs());


        //entity-information
        queue = QueueBuilder.durable("auto-task.entity-information.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-information-sync-key").noargs());

        //phases
        queue = QueueBuilder.durable("auto-task.phases.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-phases-sync-key").noargs());

        //contract-blocks
        queue = QueueBuilder.durable("auto-task.contract-blocks.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-contract-blocks-sync-key").noargs());

        //opportunities
        queue = QueueBuilder.durable("auto-task.opportunities.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-opportunities-sync-key").noargs());

        //invoices
        queue = QueueBuilder.durable("auto-task.invoices.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-invoices-sync-key").noargs());

        //roles
        queue = QueueBuilder.durable("auto-task.roles.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-roles-sync-key").noargs());

        //clientportalusers
        queue = QueueBuilder.durable("auto-task.client-portal-users.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-ask.client-portal-users-sync-key").noargs());

        //contractservicebundleunits
        queue = QueueBuilder.durable("auto-task.contract-service-bundle-units.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-contract-service-bundle-units-sync-key").noargs());

        //contract-service-units
        queue = QueueBuilder.durable("auto-task.contract-service-units.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-contract-service-units-sync-key").noargs());

        //survey-results
        queue = QueueBuilder.durable("auto-task.survey-results.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-survey-results-sync-key").noargs());

        //resources
        queue = QueueBuilder.durable("auto-task.resources.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("auto-task-resources-sync-key").noargs());

        //time entry
        queue = QueueBuilder.durable("auto-task.time-entries.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-time-entries-sync-key").noargs());


        //service-call-ticket-resources
        queue = QueueBuilder.durable("auto-task.service-call-ticket-resources.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-call-ticket-resources-sync-key").noargs());

        //service-calls
        queue = QueueBuilder.durable("auto-task.service-calls.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-calls-sync-key").noargs());


        //ConfigurationItems
        queue = QueueBuilder.durable("auto-task.configuration-items.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-configuration-items-sync-key").noargs());

        //Products
        queue = QueueBuilder.durable("auto-task.products.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-products-sync-key").noargs());


        //project-attachments
        queue = QueueBuilder.durable("auto-task.project-attachments.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-project-attachments-sync-key").noargs());

        //service-level-agreement-results
        queue = QueueBuilder.durable("auto-task.service-level-agreement-results.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-level-agreement-results-sync-key").noargs());

        //resource-role-queues
        queue = QueueBuilder.durable("auto-task.resource-role-queues.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-resource-role-queues-sync-key").noargs());

        //service-call-task-resource
        queue = QueueBuilder.durable("auto-task.service-call-task-resource.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-call-task-resource-sync-key").noargs());


        //service-call-tasks
        queue = QueueBuilder.durable("auto-task.service-call-tasks.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-call-tasks-sync-key").noargs());

        //service-bundles
        queue = QueueBuilder.durable("auto-task.service-bundles.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-bundles-sync-key").noargs());

        //service-call-tickets
        queue = QueueBuilder.durable("auto-task.service-call-tickets.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("auto-task-service-call-tickets-sync-key").noargs());

    }

    @Bean
    public void declareHubspotExchange() {
        Exchange exchange = ExchangeBuilder.directExchange("data.hub-spot.sync").build();
        this.amqpAdmin.declareExchange(exchange);
        Map<String, Object> args = new HashMap<>(2);
        args.put("x-dead-letter-exchange", "data.hub-spot.sync");
        args.put("x-dead-letter-routing-key", "hub-spot-bad-message-key");

        Queue queue = QueueBuilder.durable("hub-spot.tickets.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange)
                .with("hub-spot-tickets-sync-key").noargs());
    }

    @Bean
    public void declareTeamsExchange() {
        Exchange exchange = ExchangeBuilder.directExchange("data.teams.sync").build();
        this.amqpAdmin.declareExchange(exchange);

        Map<String, Object> args = new HashMap<>(2);
        args.put("x-dead-letter-exchange", "data.teams.sync");
        args.put("x-dead-letter-routing-key", "data-teams-bad-message-key");

        //channel
        Queue queue = QueueBuilder.durable("data-teams.group.channel.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("data-teams-groups-channel-sync-key").noargs());
        //planners
        queue = QueueBuilder.durable("data-teams.planners-tasks.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("data-teams-planners-tasks-sync-key").noargs());

    }

    @PostConstruct
    public void declareQuickBooksExchange() {
        Exchange exchange = ExchangeBuilder.directExchange("data.quick-books.sync").build();
        this.amqpAdmin.declareExchange(exchange);

        Map<String, Object> args = new HashMap<>(2);
        args.put("x-dead-letter-exchange", "data.quick-books.sync");
        args.put("x-dead-letter-routing-key", "quick-books-bad-message-key");

        Queue queue = QueueBuilder.durable("quick-books-desktop.account.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("quick-books-desktop-account-sync-key").noargs());

        queue = QueueBuilder.durable("quick-books-online.account.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("quick-books-online-account-sync-key").noargs());

        queue = QueueBuilder.durable("quick-books-desktop.customers.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("quick-books-desktop-customers-sync-key").noargs());

        queue = QueueBuilder.durable("quick-books-online.invoice.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("quick-books-online-invoice-sync-key").noargs());

//        queue = QueueBuilder.durable("quick-books-online.ProfitAndLoss.standard.tl").withArguments(args).build();
//        this.amqpAdmin.declareQueue(queue);
//        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
//                .to(exchange).with("quick-books-online-profitandloss-standard-sync-key").noargs());

        queue = QueueBuilder.durable("quick-books-online.balance.sheet.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("quick-books-online-balance-sheet-sync-key").noargs());

        queue = QueueBuilder.durable("quick-books-online.general.ledger.tl").withArguments(args).build();
        this.amqpAdmin.declareQueue(queue);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(queue)
                .to(exchange).with("quick-books-online-general-ledger-sync-key").noargs());

    }

    @Bean
    public void declareContactscienceExchange() {
        Exchange dataScienceExchange = ExchangeBuilder.directExchange("data.connector.contactscience").build();
        this.amqpAdmin.declareExchange(dataScienceExchange);

        //callblock
        Queue dataGroup = QueueBuilder.durable("contactscience.callblock.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataScienceExchange).with("contactscience-callblock-key").noargs());

        //appointments
        dataGroup = QueueBuilder.durable("contactscience.appointments.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataScienceExchange).with("contactscience-appointments-key").noargs());

    }

    @Bean
    public void declareJiraExchange() {
        Exchange dataJiraExchange = ExchangeBuilder.directExchange("data.connector.jira").build();
        this.amqpAdmin.declareExchange(dataJiraExchange);

        //project
        Queue dataGroup = QueueBuilder.durable("jira.project.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataJiraExchange).with("jira-project-key").noargs());

        //users
        dataGroup = QueueBuilder.durable("jira.user.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataJiraExchange).with("jira-user-key").noargs());

        //issue
        dataGroup = QueueBuilder.durable("jira.issue.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataJiraExchange).with("jira-issue-key").noargs());

        //worklog
        dataGroup = QueueBuilder.durable("jira.worklog.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataJiraExchange).with("jira-worklog-key").noargs());

        //sprint
        dataGroup = QueueBuilder.durable("jira.sprint.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataJiraExchange).with("jira-sprint-key").noargs());

        //team
        dataGroup = QueueBuilder.durable("jira.team.tl").build();
        this.amqpAdmin.declareQueue(dataGroup);
        this.amqpAdmin.declareBinding(BindingBuilder.bind(dataGroup)
                .to(dataJiraExchange).with("jira-team-key").noargs());
    }

    @Bean
    public MessageConverter rabbitMessageConverter(ObjectMapper objectMapper) {
        return new Jackson2JsonMessageConverter(objectMapper);
    }
}
